package me.ingxin.android.drawable

import android.graphics.*
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.OvalShape
import android.graphics.drawable.shapes.RectShape
import android.graphics.drawable.shapes.RoundRectShape
import android.graphics.drawable.shapes.Shape
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.roundToInt


/**
 * Created by ingxin on 2022/6/14
 * 大多数场景需要使用[setBounds]指定drawable所在的位置及大小
 * @param builder 构建参数
 * @param sp shape形状
 * @param roundRadius 圆角矩形圆角弧度
 * @param circle true绘制圆形，否则不是
 */
class TextDrawable private constructor(
    private val builder: Builder,
    private val sp: Shape,
    private val roundRadius: Float = 0f,
    private val circle: Boolean = false
) : ShapeDrawable(sp) {

    private val textPaint = Paint()
    private val borderPaint = Paint()
    private val tempRectF = RectF()

    private var textHeight = 0f

    init {
        //设置背景颜色
        paint.color = builder.backgroundColor

        //init border
        with(borderPaint) {
            color = builder.borderColor
            style = Paint.Style.STROKE
            isAntiAlias = true
            strokeWidth = builder.borderWidth.toFloat()
        }

        //init text paint
        with(textPaint) {
            color = builder.textColor
            textSize = builder.textSize.toFloat()
            isAntiAlias = true
            isFakeBoldText = builder.bold
            style = Paint.Style.FILL
        }

        //get text height
        val metrics = textPaint.fontMetrics
        textHeight = metrics.descent - metrics.ascent

    }

    private fun getTextWidth(): Float {
        //get text width
        val text = builder.content
        if (text?.isNotEmpty() == true) {
            return textPaint.measureText(text)
        }
        return 0f
    }

    override fun onDraw(shape: Shape, canvas: Canvas, paint: Paint) {
        super.onDraw(shape, canvas, paint)

        //绘制边框
        val w = builder.borderWidth / 2
        if (w > 0) {
            //super已经对canvas做了偏移，所以这里不需要在偏移
            tempRectF.set(0f, 0f, bounds.width().toFloat(), bounds.height().toFloat())
            val rect = tempRectF
            when (sp) {
                is OvalShape -> canvas.drawOval(rect, borderPaint)
                is RoundRectShape -> canvas.drawRoundRect(
                    rect,
                    roundRadius,
                    roundRadius,
                    borderPaint
                )
                else -> canvas.drawRect(rect, borderPaint)
            }
        }

        //绘制文字
        builder.content?.let {
            val x =
                (intrinsicWidth - builder.paddingLeft - builder.paddingRight - getTextWidth()) / 2f + builder.paddingLeft
            val availableHeight = (intrinsicHeight - builder.paddingTop - builder.paddingBottom)
            val y =
                (availableHeight - textHeight) / 2f + abs(textPaint.fontMetrics.ascent) + builder.paddingTop
            canvas.drawText(it, x, y, textPaint)
        }
    }

    private fun drawableWidth(): Int {
        //使用指定的大小
        if (builder.width > 0) {
            return builder.width
        }
        return (getTextWidth() + builder.paddingLeft + builder.paddingRight).toInt()
    }

    private fun drawableHeight(): Int {
        val txtH = if (builder.content?.isNotEmpty() == true) {
            textHeight
        } else {
            0f
        }.roundToInt()

        //使用指定的大小
        if (builder.height > 0) {
            return max(builder.height, txtH)
        }
        return txtH + builder.paddingTop + builder.paddingBottom
    }

    /**
     * drawable自己的宽度
     */
    override fun getIntrinsicWidth(): Int {
        val w = drawableWidth()
        if (!circle || sp !is OvalShape) {
            return w
        }
        val h = drawableHeight()
        return max(w, h)
    }

    /**
     * drawable自己的高度
     */
    override fun getIntrinsicHeight(): Int {
        val h = drawableHeight()
        if (!circle || sp !is OvalShape) {
            return h
        }
        val w = drawableWidth()
        return max(w, h)
    }

    fun getContent(): String? {
        return builder.content
    }

    /**
     * @param width 指定drawable宽度，-1为自适应
     * @param height 指定drawable高度，-1为自适应
     */
    class Builder(val width: Int = -1, val height: Int = -1) {

        /**字体颜色*/
        var textColor = Color.WHITE

        /**字体是否加粗*/
        var bold = false

        /**显示文本*/
        var content: String? = null

        /**字体大小，单位px*/
        var textSize = 14

        /**drawable左padding*/
        var paddingLeft = 0

        /**drawable右padding*/
        var paddingRight = 0

        /**drawable上padding*/
        var paddingTop = 0

        /**drawable下padding*/
        var paddingBottom = 0

        /**背景颜色*/
        var backgroundColor = Color.TRANSPARENT

        /**边框宽度，单位px*/
        var borderWidth = 0

        /**边框颜色*/
        var borderColor = Color.WHITE

        /**
         * 构建矩形的drawable
         */
        fun build(): TextDrawable {
            return TextDrawable(this, RectShape())
        }

        /**
         * 构建圆角矩形的drawable
         */
        fun buildRoundRect(radius: Float): TextDrawable {
            return TextDrawable(
                this,
                RoundRectShape(
                    floatArrayOf(
                        radius,
                        radius,
                        radius,
                        radius,
                        radius,
                        radius,
                        radius,
                        radius
                    ), null, null
                ),
                radius
            )
        }

        /**
         * 构建椭圆形的drawable
         */
        fun buildOval(): TextDrawable {
            return TextDrawable(this, OvalShape())
        }

        /**
         * 构建圆形的drawable
         */
        fun buildCircle(): TextDrawable {
            return TextDrawable(this, OvalShape(), circle = true)
        }

    }

}